<template>
  <div v-if = "isshow">
    roles
  </div>
  <div v-else>
    <self-breadcrumb :bread-arr = "rolesBread"></self-breadcrumb>
    <el-card class = "box-card">
      <div slot = "header">
        <el-button type = "primary" @click = "addRolesVisible = true">添加角色</el-button>
      </div>
      <el-table
        :data = "rolesList"
        border
        stripe
        style = "width: 100%">
        <!-- 当type=expand时就是一个可以展开的table行，展开的内容就是标签间的内容 -->
        <el-table-column
          type = "expand">
          <template slot-scope = "scope">
            <el-row v-for = "(item,index) in scope.row.children"
                    :key = "index"
                    class = "bb"
                    :class = "{'bt':index===0}"
                    align = "middle"
                    type = "flex">
              <el-col :span = "5">
                <el-tag type = "success">{{item.authName}}</el-tag>
              </el-col>
              <el-col :span = "19">
                <el-row v-for = "(sitem,sindex) in item.children"
                        :key = "sindex"
                        :class = "{'bt':sindex!==0}"
                        align = "middle"
                        type = "flex">
                  <el-col :span = "6">
                    <el-tag>{{sitem.authName}}</el-tag>
                  </el-col>
                  <el-col :span = "18">
                    <el-tag v-for = "(titem,tindex) in sitem.children"
                            :key = "tindex"
                            type = "warning">
                      {{titem.authName}}
                    </el-tag>
                  </el-col>
                </el-row>
              </el-col>
            </el-row>
          </template>
        </el-table-column>
        <el-table-column
          type = "index"
          label = "#">
        </el-table-column>
        <el-table-column
          prop = "roleName"
          label = "角色名称">
        </el-table-column>
        <el-table-column
          prop = "roleDesc"
          label = "角色描述">
        </el-table-column>
        <el-table-column
          label = "操作">
          <template slot-scope = "scope">
            <el-button size = "small" type = "primary" icon = "el-icon-edit" @click = "editRoles(scope.row)">编辑
            </el-button>
            <el-button size = "small" type = "warning" icon = "el-icon-s-custom"
                       @click = "assignPermissions(scope.row)">分配权限
            </el-button>
            <el-button size = "small" type = "danger" icon = "el-icon-delete" @click = "deleteRole(scope.row)">删除
            </el-button>
          </template>
        </el-table-column>
      </el-table>
    </el-card>
    <el-dialog
      title = "分配权限"
      :visible.sync = "assignVisible"
      width = "30%">
      <!--
      el的树形控件，需要绑定数据和下一级的属性名，及其label名  还提供了结点点击事件，默认传入当前被点击的结点
      accordion是手风琴效果也就是同时只能打开一个结点    show-checkout 展现复选框让树形控件可以选中
      node-key是每一个树节点的唯一标识，可以使用数据中的id值，比如这里node-key的值就是id表示id属性，而不是动态绑定某个动态的值，
      default-checked-keys是默认勾选，传入一个数组，值应该为需要被勾选的元素的node-key
       -->
      <el-tree
        ref = "elTree"
        :data = "permissionsTree"
        :props = "permissionsProps"
        accordion
        show-checkbox
        :default-checked-keys = "defaultCheckedKeys"
        node-key = "id"
        @node-click = "handleNodeClick"></el-tree>
      <span slot = "footer" class = "dialog-footer">
        <el-button @click = "assignVisible = false">取 消</el-button>
        <el-button type = "primary" @click = "allotRights">确 定</el-button>
      </span>
    </el-dialog>
    <el-dialog
      title = "提示"
      :visible.sync = "addRolesVisible"
      width = "50%">
      <el-form ref = "addForm" :model = "addRolesForm" :rules = "addRolesRules" label-width = "80px">
        <!--
        校验要想正确的话 还需要校验的字段名称与输入的名称相同 比如这里的 prop="rolename" 所以v-model也只能绑定rolename
        在prop中可以使用大写字母 应该是在html原生属性中不能使用大写字母 如果是vue中的属性值或者vue处理了的属性值都可以使用大写字母
        但是标签一定是小写的！！
         -->
        <el-form-item label = "角色名称" prop = "roleName">
          <el-input v-model = "addRolesForm.roleName" clearable></el-input>
        </el-form-item>
        <el-form-item label = "角色描述">
          <el-input v-model = "addRolesForm.roleDesc" clearable></el-input>
        </el-form-item>
      </el-form>
      <span slot = "footer" class = "dialog-footer">
        <el-button @click = "addRolesVisible = false">取 消</el-button>
        <el-button type = "primary" @click = "addRoles">确 定</el-button>
      </span>
    </el-dialog>
    <el-dialog
      title = "编辑角色"
      :visible.sync = "editRolesVisible"
      width = "30%">
      <el-form ref = "editForm" :model = "addRolesForm" :rules = "addRolesRules" label-width = "80px">
        <el-form-item label = "角色名称" prop = "roleName">
          <el-input v-model = "addRolesForm.roleName"></el-input>
        </el-form-item>
        <el-form-item label = "角色描述">
          <el-input v-model = "addRolesForm.roleDesc"></el-input>
        </el-form-item>
      </el-form>
      <span slot = "footer" class = "dialog-footer">
        <el-button @click = "editRolesVisible = false">取 消</el-button>
        <el-button type = "primary" @click = "editRolesDefine">确 定</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
import SelfBreadcrumb from '../SelfBreadcrumb'

export default {
  name: 'Roles',
  components: {
    SelfBreadcrumb
  },
  created () {
    this.getRoles()
  },
  data () {
    return {
      isshow: false,
      rolesList: [],
      roleId: '',
      rolesBread: ['权限管理', '角色列表'],
      assignVisible: false,
      permissionsTree: [],
      defaultCheckedKeys: [],
      permissionsProps: {
        children: 'children',
        label: 'authName'
      },
      addRolesVisible: false,
      addRolesForm: {
        roleName: '',
        roleDesc: ''
      },
      addRolesRules: {
        roleName: [
          { required: true, message: '请输入角色名称', trigger: 'blur' }
        ]
      },
      editRolesVisible: false
    }
  },
  methods: {
    getRoles () {
      this.$http.get('roles').then(ret => {
        const data = ret.data
        if (data.meta.status === 200 || data.meta.status === 201 || data.meta.status === 204) {
          this.$message.success(data.meta.msg)
          this.rolesList = data.data
        } else {
          this.$message.error(data.meta.msg)
          this.isshow = true
        }
      })
    },
    assignPermissions (row) {
      this.roleId = row.id
      this.$http.get('rights/tree').then(ret => {
        this.$process(ret, this.getRoles)
        this.permissionsTree = ret.data.data
        // 这里的操作是获取角色的权限，用于树形组件中的默认勾选，  这里是采用了遍历的方式，因为层数还不是很多
        // 但是当层数较多时，建议使用递归的方式
        const tree = row.children
        const arr = []
        tree.forEach(item => {
          const second = item.children
          for (let i = 0; i < second.length; i++) {
            const third = second[i].children
            for (const j of third) arr.push(j.id)
          }
        })
        this.assignVisible = true
        this.defaultCheckedKeys = arr
        console.log(this.defaultCheckedKeys)
      })
    },
    handleNodeClick (data) {
      console.log(data)
    },
    async allotRights () {
      const keys = [
        ...this.$refs.elTree.getCheckedKeys(),
        ...this.$refs.elTree.getHalfCheckedKeys()
      ]
      const rids = keys.join(',')
      // 对象结构赋值  注意对象的结构赋值重要的一定是键名  只有键名匹配上了才可以
      /*
        * 比如  let { aa : bb} ={aa:123}  那么bb=123    也就是键名用于匹配 键值才是被赋值的变量
        * 所以这里的结构赋值使用data来匹配返回值中的data并赋值给res
        * */
      console.log(this.roleId, 'rids=' + rids, 'keys=' + keys)
      const { data: res } = await this.$http.post(`roles/${this.roleId}/rights`, { rids })
      if (res.meta.status === 200) {
        this.$message.success(res.meta.msg)
      } else {
        this.$message.error(res.meta.msg)
      }
      this.getRoles()
      this.assignVisible = false
    },
    async addRoles () {
      this.$refs.addForm.validate(valid => {
        if (!valid) return
      })
      const { data: res } = await this.$http.post('roles', this.addRolesForm)
      if (res.meta.status === 201) { this.$message.success(res.meta.msg) } else { this.$message.error(res.meta.msg) }
      this.getRoles()
      this.$refs.addForm.resetFields()
      this.addRolesVisible = false
    },
    editRoles (row) {
      this.roleId = row.id
      this.addRolesForm.roleName = row.roleName
      this.addRolesForm.roleDesc = row.roleDesc
      this.editRolesVisible = true
    },
    async editRolesDefine () {
      this.$refs.editForm.validate(valid => {
        if (!valid) return
      })
      const { data: res } = await this.$http.put(`roles/${this.roleId}`, {
        id: this.roleId,
        ...this.addRolesForm
      })
      if (res.meta.status === 200) { this.$message.success(res.meta.msg) } else { this.$message.error(res.meta.msg) }
      this.getRoles()
      this.editRolesVisible = false
    },
    async deleteRole (row) {
      const { data: res } = await this.$http.delete(`roles/${row.id}`)
      if (res.meta.status === 200) { this.$message.success(res.meta.msg) } else { this.$message.success(res.meta.msg) }
      this.getRoles()
    }
  }
}
</script>

<style scoped>
  .el-card {
    margin-top: 20px;
  }

  .bt {
    border-top: 1px #999 solid;
  }

  .bb {
    border-bottom: 1px #999 solid;
  }

  .el-tag {
    margin: 8px;
  }

</style>
